package impl

import (
	"adam2/internal/constants"
	"adam2/internal/model"
	"adam2/internal/properties"
	"adam2/internal/util"
	"anubis-framework/pkg/io"
	"fmt"
)

type Robot7StockTransactRecordDaoImpl struct {
	*BaseDaoImpl
}

// 返回dao实现类
func GetRobot7StockTransactRecordDaoImpl() *Robot7StockTransactRecordDaoImpl {
	return &Robot7StockTransactRecordDaoImpl{GetBaseDaoImpl()}
}

// 返回表名
func (_robot7StockTransactRecordDaoImpl *Robot7StockTransactRecordDaoImpl) FindTableName() string {
	return "ROBOT7_STOCK_TRANSACT_RECORD"
}

// 卖股票
func (_robot7StockTransactRecordDaoImpl *Robot7StockTransactRecordDaoImpl) SellOrBuy_stock(currentDate string, mandatoryStopLoss bool, mandatoryStopLossRate float64) {
	io.Infoln("卖股票")

	// robot7_account表的所有记录
	var robot7AccountArray model.Robot7AccountArray
	_robot7StockTransactRecordDaoImpl.db.Table("robot7_account").Select("*").Order("id_ asc").Find(&robot7AccountArray)

	for _, robot7Account := range robot7AccountArray {
		// 如果这个账户没有持有股票，则查找下一个账户
		if robot7Account.HoldStockNumber == 0 {
			io.Infoln("账号[%s]持股数量为0，不需要卖出股票", (*robot7Account).RobotName)
			continue
		}

		// 做多
		// 某个机器人账户的买入的股票的交易记录
		var robot7StockTransactRecordArray model.Robot7StockTransactRecordArray
		_robot7StockTransactRecordDaoImpl.db.Raw("select * from robot7_stock_transact_record t "+
			"where t.robot_name = ? and t.SELL_DATE is null "+
			"and t.SELL_PRICE is null and t.SELL_AMOUNT is null "+
			"and t.direction = 1", robot7Account.RobotName).Scan(&robot7StockTransactRecordArray)
		for _, robot7StockTransactRecord := range robot7StockTransactRecordArray {
			// 是否卖出/买入。true表示准备卖出/买入，false表示不准备卖出/买入
			var doSellBuy bool = false

			var stockTransactionDataAll model.StockTransactionDataAll
			_robot7StockTransactRecordDaoImpl.db.Raw("select * from stock_transaction_data_all t "+
				"where t.code_ = ? and t.date_=to_date(?, 'yyyy-mm-dd')", robot7StockTransactRecord.StockCode, currentDate).Scan(&stockTransactionDataAll)

			// 如果这只股票当天出现下跌，则卖出
			if properties.Robot7Properties_.TransactionStrategyInBull == 1 {
				if stockTransactionDataAll.ChangeRange < 0 {
					io.Infoln("股票[%s]在日期[%s]下跌了[%f]，因此被卖出", robot7StockTransactRecord.StockCode, currentDate, stockTransactionDataAll.ChangeRange)
					doSellBuy = true
				}
			}

			// 卖出价格，用于判断是否强制止损
			var sellPriceForMandatoryStop float64 = 0
			// 判断是否有强制止损
			if properties.Robot7Properties_.MandatoryStopLoss == true {
				_robot7StockTransactRecordDaoImpl.db.Raw("select t1.close_price from stock_transaction_data_all t1 "+
					"where t1.code_ = ? and t1.date_ = to_date(?, 'yyyy-mm-dd')",
					robot7StockTransactRecord.StockCode, currentDate).Scan(&sellPriceForMandatoryStop)
				if sellPriceForMandatoryStop == 0 {
					// 说明股票在这一天没有交易记录
					io.Infoln("股票[%s]在日期[%s]没有交易记录", robot7StockTransactRecord.StockCode, currentDate)
				} else {
					if (sellPriceForMandatoryStop-robot7StockTransactRecord.BuyPrice)/robot7StockTransactRecord.BuyPrice*100 <=
						-properties.Robot7Properties_.MandatoryStopLossRate {

						io.Infoln("股票[%s]在日期[%s]损失超过了[%f]，因此被强制止损", robot7StockTransactRecord.StockCode, currentDate, properties.Robot7Properties_.MandatoryStopLossRate)

						// 更新robot7_stock_transact_record表的sell_date、sell_price和sell_amount字段
						_robot7StockTransactRecordDaoImpl.db.Exec("update robot7_stock_transact_record t "+
							"set t.sell_date = to_date(?, 'yyyy-mm-dd'), t.sell_price  = ?, t.sell_amount = t.buy_amount, "+
							"t.stamp_duty = ?, t.registration_fee_when_sell = ?, t.commission_when_sell = ? "+
							"where t.id_ = ?",
							currentDate, sellPriceForMandatoryStop,
							util.CalculateStampDuty(sellPriceForMandatoryStop, robot7StockTransactRecord.BuyAmount),
							util.CalculateRegistrationFee(robot7StockTransactRecord.StockCode, robot7StockTransactRecord.BuyAmount),
							util.CalculateCommission(sellPriceForMandatoryStop, robot7StockTransactRecord.BuyAmount),
							robot7StockTransactRecord.ID)

						// 更新robot7_stock_transact_record表的profit_and_loss和profit_and_loss_rate字段
						_robot7StockTransactRecordDaoImpl.db.Exec("update robot7_stock_transact_record t "+
							"set t.profit_and_loss = ROUND((t.sell_price * t.sell_amount) - (t.buy_price * t.buy_amount)), "+
							"t.profit_and_loss_rate = (t.sell_price - t.buy_price) / t.buy_price * 100, "+
							"t.stamp_duty = t.stamp_duty + ?, "+
							"t.registration_fee_when_sell = t.registration_fee_when_sell + ?, "+
							"t.commission_when_sell = t.commission_when_sell + ? "+
							"where t.id_ = ?",
							util.CalculateStampDuty(sellPriceForMandatoryStop, robot7StockTransactRecord.BuyAmount),
							util.CalculateRegistrationFee(robot7StockTransactRecord.StockCode, robot7StockTransactRecord.BuyAmount),
							util.CalculateCommission(sellPriceForMandatoryStop, robot7StockTransactRecord.BuyAmount),
							robot7StockTransactRecord.ID)

						continue
					}
				}
			}

			// 判断是否是死叉，如果不是死叉，则返回下一条记录
			if properties.Robot7Properties_.TransactionStrategyInBull == 2 {
				var sellOrBuyPrice float64 = 0
				// MACD死叉
				if robot7StockTransactRecord.FilterType == constants.MACD_GOLD_CROSS {
					//var macdGoldCrossNumber int = 0
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_macd_gold_cross t "+
						"where t.stock_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
					if sellOrBuyPrice > 0 {
						doSellBuy = true
					}
				}
				// 收盘价死叉五日均线
				if robot7StockTransactRecord.FilterType == constants.CLOSE_PRICE_MA5_GOLD_CROSS {
					//var closePriceMa5GoldCrossNumber int = 0
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_close_price_ma5_gold_cross t "+
						"where t.stock_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
					if sellOrBuyPrice > 0 {
						doSellBuy = true
					}
				}
				// 平均K线是否从上涨趋势变为下跌趋势
				if robot7StockTransactRecord.FilterType == constants.HEI_KIN_ASHI_UP {
					//var heiKinAshiUpNumber int = 0
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_hei_kin_ashi_up_down t "+
						"where t.stock_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
					if sellOrBuyPrice > 0 {
						doSellBuy = true
					}
				}
				// KD死叉
				if robot7StockTransactRecord.FilterType == constants.KD_GOLD_CROSS {
					//var kdGoldCrossNumber int = 0
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_kd_gold_cross t "+
						"where t.stock_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
					if sellOrBuyPrice > 0 {
						doSellBuy = true
					}
				}
			}

			// 无论第二天是涨是跌，全部卖出
			if properties.Robot7Properties_.TransactionStrategyInBull == 3 {
				io.Infoln("股票[%s]，无论第二天是涨是跌，全部卖出", robot7StockTransactRecord.StockCode)
				doSellBuy = true
			}

			// 判断是否是死叉，如果不是死叉，则返回下一条记录
			if properties.Robot7Properties_.TransactionStrategyInBull == 4 {
				var sellOrBuyPrice float64 = 0
				// MACD死叉
				if robot7StockTransactRecord.FilterType == constants.CLOSE_PRICE_GOLD_CROSS_BULL_SHORT_LINE {
					//var macdGoldCrossNumber int = 0
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_bull_short_line_up t "+
						"where t.stock_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
					if sellOrBuyPrice > 0 {
						doSellBuy = true
					}
				}
			}

			if doSellBuy == true {
				// 如果是死叉，则卖出这支股票
				// 更新robot7_stock_transact_record表的sell_date、sell_price和sell_amount字段
				_robot7StockTransactRecordDaoImpl.db.Exec("update robot7_stock_transact_record t "+
					"set t.sell_date = to_date(?, 'yyyy-mm-dd'), t.sell_price  = ?, t.sell_amount = t.buy_amount,"+
					"t.stamp_duty = ROUND(t.buy_amount * "+fmt.Sprintf("%f", stockTransactionDataAll.ClosePrice)+" * "+fmt.Sprintf("%f", properties.Robot7Properties_.StampDutyRate)+", 2),"+
					"t.registration_fee_when_sell = ?,"+
					"t.commission_when_sell = ? "+
					"where t.id_ = ?",
					currentDate, stockTransactionDataAll.ClosePrice,
					util.CalculateRegistrationFee(robot7StockTransactRecord.StockCode, robot7StockTransactRecord.BuyAmount),
					util.CalculateCommission(stockTransactionDataAll.ClosePrice, robot7StockTransactRecord.BuyAmount),
					robot7StockTransactRecord.ID)

				// 更新robot7_stock_transact_record表的profit_and_loss和profit_and_loss_rate字段
				_robot7StockTransactRecordDaoImpl.db.Exec("update robot7_stock_transact_record t "+
					"set t.profit_and_loss = ROUND((t.sell_price * t.sell_amount) - (t.buy_price * t.buy_amount)), "+
					"t.profit_and_loss_rate = (t.sell_price - t.buy_price) / t.buy_price * 100 "+
					"where t.id_ = ?", robot7StockTransactRecord.ID)
			}
		}
	}
}

// 卖股票/ETF
func (_robot7StockTransactRecordDaoImpl *Robot7StockTransactRecordDaoImpl) SellOrBuy_all(currentDate string, mandatoryStopLoss bool, mandatoryStopLossRate float64) {
	io.Infoln("卖股票/ETF")

	// robot7_account表的所有记录
	var robot7AccountArray model.Robot7AccountArray
	_robot7StockTransactRecordDaoImpl.db.Table("robot7_account").Select("*").Order("id_ asc").Find(&robot7AccountArray)

	for _, robot7Account := range robot7AccountArray {
		// 如果这个账户没有持股票/ETF，则查找下一个账户
		if robot7Account.HoldStockNumber == 0 {
			io.Infoln("账号[%s]持股票/ETF数量为0，不需要卖出股票/ETF", (*robot7Account).RobotName)
			continue
		}

		// 做多
		// 某个机器人账户的买入的股票/ETF的交易记录
		var robot7StockTransactRecordArray model.Robot7StockTransactRecordArray
		_robot7StockTransactRecordDaoImpl.db.Raw("select * from robot7_stock_transact_record t "+
			"where t.robot_name = ? and t.SELL_DATE is null "+
			"and t.SELL_PRICE is null and t.SELL_AMOUNT is null "+
			"and t.direction = 1", robot7Account.RobotName).Scan(&robot7StockTransactRecordArray)
		for _, robot7StockTransactRecord := range robot7StockTransactRecordArray {
			// 是否卖出/买入。true表示准备卖出/买入，false表示不准备卖出/买入
			var doSellBuy bool = false
			var closePrice float64

			var stockTransactionDataAll model.StockTransactionDataAll
			var etfTransactionData model.EtfTransactionData
			// 股票
			if robot7StockTransactRecord.TransactionType == constants.STOCK {
				_robot7StockTransactRecordDaoImpl.db.Raw("select * from stock_transaction_data_all t "+
					"where t.code_ = ? and t.date_=to_date(?, 'yyyy-mm-dd')", robot7StockTransactRecord.StockCode, currentDate).Scan(&stockTransactionDataAll)
				closePrice = stockTransactionDataAll.ClosePrice
				// 如果没有查找到记录，可能是因为这个股票在这个交易日停牌，因此跳过这条记录
				if stockTransactionDataAll.ID == 0 {
					io.Infoln("股票[%s]在日期[%s]没有查找到记录，可能是因为这个股票在这个交易日停牌，因此跳过这条记录", robot7StockTransactRecord.StockCode, currentDate)
					continue
				}
			}
			// ETF
			if robot7StockTransactRecord.TransactionType == constants.ETF {
				_robot7StockTransactRecordDaoImpl.db.Raw("select * from etf_transaction_data t "+
					"where t.code_ = ? and t.date_=to_date(?, 'yyyy-mm-dd')", robot7StockTransactRecord.StockCode, currentDate).Scan(&etfTransactionData)
				closePrice = etfTransactionData.ClosePrice
				// 如果没有查找到记录，可能是因为这个ETF在这个交易日停牌，因此跳过这条记录
				if etfTransactionData.ID == 0 {
					io.Infoln("ETF[%s]在日期[%s]没有查找到记录，可能是因为这个ETF在这个交易日停牌，因此跳过这条记录", etfTransactionData.Code, currentDate)
					continue
				}
			}
			// 如果这只股票/ETF当天出现下跌，则卖出
			if robot7StockTransactRecord.TransactionType == constants.STOCK && properties.Robot7Properties_.TransactionStrategyInBull == 1 {
				if stockTransactionDataAll.ChangeRange < 0 {
					io.Infoln("股票[%s]在日期[%s]下跌了[%f]，因此被卖出", robot7StockTransactRecord.StockCode, currentDate, stockTransactionDataAll.ChangeRange)
					doSellBuy = true
				}
			}
			if robot7StockTransactRecord.TransactionType == constants.ETF && properties.Robot7Properties_.TransactionStrategyInShort == 1 {
				if etfTransactionData.ChangeRange < 0 {
					io.Infoln("ETF[%s]在日期[%s]下跌了[%f]，因此被卖出", robot7StockTransactRecord.StockCode, currentDate, etfTransactionData.ChangeRange)
					doSellBuy = true
				}
			}
			// 如果这只股票/ETF当天出现向下突破，则卖出
			if robot7StockTransactRecord.TransactionType == constants.SHORT && properties.Robot7Properties_.TransactionStrategyInBull == 5 {
				var lastStockTransactionDataAll model.StockTransactionDataAll
				_robot7StockTransactRecordDaoImpl.db.Raw("select * from ("+
					"select * from stock_transaction_data_all t where t.code_=? and t.date_<to_date(?,'yyyy-mm-dd') "+
					"order by t.date_ desc) where rownum<=1", stockTransactionDataAll.Code, currentDate).Scan(&lastStockTransactionDataAll)
				// 如果前一天是阳线，当天是阴线，并且当天收盘价低于前一天开盘价，则卖出
				if lastStockTransactionDataAll.ChangeRange >= 0 && stockTransactionDataAll.ChangeRange < 0 && stockTransactionDataAll.ClosePrice < lastStockTransactionDataAll.OpenPrice {
					io.Infoln("如果前一天[%s]是阳线，当天[%s]是阴线，并且当天收盘价[%f]低于前一天开盘价[%f]，则卖出", lastStockTransactionDataAll.Date,
						stockTransactionDataAll.Date, stockTransactionDataAll.ClosePrice, lastStockTransactionDataAll.OpenPrice)
					doSellBuy = true
				}
				// 如果前一天是阳线，当天是阳线，并且当天收盘价低于前一天开盘价，则卖出
				if lastStockTransactionDataAll.ChangeRange >= 0 && stockTransactionDataAll.ChangeRange >= 0 && stockTransactionDataAll.ClosePrice < lastStockTransactionDataAll.OpenPrice {
					io.Infoln("如果前一天[%s]是阳线，当天[%s]是阳线，并且当天收盘价[%f]低于前一天开盘价[%f]，则卖出", lastStockTransactionDataAll.Date,
						stockTransactionDataAll.Date, stockTransactionDataAll.ClosePrice, lastStockTransactionDataAll.OpenPrice)
					doSellBuy = true
				}
				// 如果前一天是阴线，当天是阳线，并且当天收盘价低于前一天收盘价，则卖出
				if lastStockTransactionDataAll.ChangeRange < 0 && stockTransactionDataAll.ChangeRange >= 0 && stockTransactionDataAll.ClosePrice < lastStockTransactionDataAll.ClosePrice {
					io.Infoln("如果前一天[%s]是阴线，当天[%s]是阳线，并且当天收盘价[%f]低于前一天收盘价[%f]，则卖出", lastStockTransactionDataAll.Date,
						stockTransactionDataAll.Date, stockTransactionDataAll.ClosePrice, lastStockTransactionDataAll.OpenPrice)
					doSellBuy = true
				}
				// 如果前一天是阴线，当天是阴线，并且当天收盘价低于前一天收盘价，则卖出
				if lastStockTransactionDataAll.ChangeRange < 0 && stockTransactionDataAll.ChangeRange < 0 && stockTransactionDataAll.ClosePrice < lastStockTransactionDataAll.ClosePrice {
					io.Infoln("如果前一天[%s]是阴线，当天[%s]是阴线，并且当天收盘价[%f]低于前一天收盘价[%f]，则卖出", lastStockTransactionDataAll.Date,
						stockTransactionDataAll.Date, stockTransactionDataAll.ClosePrice, lastStockTransactionDataAll.OpenPrice)
					doSellBuy = true
				}
			}
			if robot7StockTransactRecord.TransactionType == constants.ETF && properties.Robot7Properties_.TransactionStrategyInShort == 5 {
				var lastEtfTransactionData model.EtfTransactionData
				_robot7StockTransactRecordDaoImpl.db.Raw("select * from ("+
					"select * from etf_transaction_data t where t.code_=? and t.date_<to_date(?,'yyyy-mm-dd') "+
					"order by t.date_ desc) where rownum<=1", etfTransactionData.Code, currentDate).Scan(&lastEtfTransactionData)
				// 如果前一天是阳线，当天是阴线，并且当天收盘价低于前一天开盘价，则卖出
				if lastEtfTransactionData.ChangeRange >= 0 && etfTransactionData.ChangeRange < 0 && etfTransactionData.ClosePrice < lastEtfTransactionData.OpenPrice {
					io.Infoln("如果前一天[%s]是阳线，当天[%s]是阴线，并且当天收盘价[%f]低于前一天开盘价[%f]，则卖出", lastEtfTransactionData.Date,
						etfTransactionData.Date, etfTransactionData.ClosePrice, lastEtfTransactionData.OpenPrice)
					doSellBuy = true
				}
				// 如果前一天是阳线，当天是阳线，并且当天收盘价低于前一天开盘价，则卖出
				if lastEtfTransactionData.ChangeRange >= 0 && etfTransactionData.ChangeRange >= 0 && etfTransactionData.ClosePrice < lastEtfTransactionData.OpenPrice {
					io.Infoln("如果前一天[%s]是阳线，当天[%s]是阳线，并且当天收盘价[%f]低于前一天开盘价[%f]，则卖出", lastEtfTransactionData.Date,
						etfTransactionData.Date, etfTransactionData.ClosePrice, lastEtfTransactionData.OpenPrice)
					doSellBuy = true
				}
				// 如果前一天是阴线，当天是阳线，并且当天收盘价低于前一天收盘价，则卖出
				if lastEtfTransactionData.ChangeRange < 0 && etfTransactionData.ChangeRange >= 0 && etfTransactionData.ClosePrice < lastEtfTransactionData.ClosePrice {
					io.Infoln("如果前一天[%s]是阴线，当天[%s]是阳线，并且当天收盘价[%f]低于前一天收盘价[%f]，则卖出", lastEtfTransactionData.Date,
						etfTransactionData.Date, etfTransactionData.ClosePrice, lastEtfTransactionData.OpenPrice)
					doSellBuy = true
				}
				// 如果前一天是阴线，当天是阴线，并且当天收盘价低于前一天收盘价，则卖出
				if lastEtfTransactionData.ChangeRange < 0 && etfTransactionData.ChangeRange < 0 && etfTransactionData.ClosePrice < lastEtfTransactionData.ClosePrice {
					io.Infoln("如果前一天[%s]是阴线，当天[%s]是阴线，并且当天收盘价[%f]低于前一天收盘价[%f]，则卖出", lastEtfTransactionData.Date,
						etfTransactionData.Date, etfTransactionData.ClosePrice, lastEtfTransactionData.OpenPrice)
					doSellBuy = true
				}
			}

			// 卖出价格，用于判断是否强制止损
			var sellPriceForMandatoryStop float64 = 0
			// 判断是否有强制止损
			if properties.Robot7Properties_.MandatoryStopLoss == true {
				// 股票
				if robot7StockTransactRecord.TransactionType == constants.STOCK {
					_robot7StockTransactRecordDaoImpl.db.Raw("select t1.close_price from stock_transaction_data_all t1 "+
						"where t1.code_ = ? and t1.date_ = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellPriceForMandatoryStop)
				}
				// ETF
				if robot7StockTransactRecord.TransactionType == constants.ETF {
					_robot7StockTransactRecordDaoImpl.db.Raw("select t1.close_price from etf_transaction_data t1 "+
						"where t1.code_ = ? and t1.date_ = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellPriceForMandatoryStop)
				}

				if sellPriceForMandatoryStop == 0 {
					// 说明股票/ETF在这一天没有交易记录
					io.Infoln("股票/ETF[%s]在日期[%s]没有交易记录", robot7StockTransactRecord.StockCode, currentDate)
				} else {
					if (sellPriceForMandatoryStop-robot7StockTransactRecord.BuyPrice)/robot7StockTransactRecord.BuyPrice*100 <=
						-properties.Robot7Properties_.MandatoryStopLossRate {

						io.Infoln("股票/ETF[%s]在日期[%s]损失超过了[%f]，因此被强制止损", robot7StockTransactRecord.StockCode, currentDate, properties.Robot7Properties_.MandatoryStopLossRate)

						// 更新robot7_stock_transact_record表的sell_date、sell_price和sell_amount字段
						_robot7StockTransactRecordDaoImpl.db.Exec("update robot7_stock_transact_record t "+
							"set t.sell_date = to_date(?, 'yyyy-mm-dd'), t.sell_price  = ?, t.sell_amount = t.buy_amount, "+
							"t.stamp_duty = ?, t.registration_fee_when_sell = ?, t.commission_when_sell = ? "+
							"where t.id_ = ?",
							currentDate, sellPriceForMandatoryStop,
							util.CalculateStampDuty(sellPriceForMandatoryStop, robot7StockTransactRecord.BuyAmount),
							util.CalculateRegistrationFee(robot7StockTransactRecord.StockCode, robot7StockTransactRecord.BuyAmount),
							util.CalculateCommission(sellPriceForMandatoryStop, robot7StockTransactRecord.BuyAmount),
							robot7StockTransactRecord.ID)

						// 更新robot7_stock_transact_record表的profit_and_loss和profit_and_loss_rate字段
						_robot7StockTransactRecordDaoImpl.db.Exec("update robot7_stock_transact_record t "+
							"set t.profit_and_loss = ROUND((t.sell_price * t.sell_amount) - (t.buy_price * t.buy_amount)), "+
							"t.profit_and_loss_rate = (t.sell_price - t.buy_price) / t.buy_price * 100, "+
							"t.stamp_duty = t.stamp_duty + ?, "+
							"t.registration_fee_when_sell = t.registration_fee_when_sell + ?, "+
							"t.commission_when_sell = t.commission_when_sell + ? "+
							"where t.id_ = ?",
							util.CalculateStampDuty(sellPriceForMandatoryStop, robot7StockTransactRecord.BuyAmount),
							util.CalculateRegistrationFee(robot7StockTransactRecord.StockCode, robot7StockTransactRecord.BuyAmount),
							util.CalculateCommission(sellPriceForMandatoryStop, robot7StockTransactRecord.BuyAmount),
							robot7StockTransactRecord.ID)

						continue
					}
				}
			}

			// 判断是否是死叉，如果不是死叉，则返回下一条记录
			var sellOrBuyPrice float64 = 0
			// MACD死叉
			if robot7StockTransactRecord.FilterType == constants.MACD_GOLD_CROSS {
				// 股票
				if properties.Robot7Properties_.TransactionStrategyInBull == 2 && robot7StockTransactRecord.TransactionType == constants.STOCK {
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_macd_gold_cross t "+
						"where t.etf_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
				}
				// ETF
				if properties.Robot7Properties_.TransactionStrategyInShort == 2 && robot7StockTransactRecord.TransactionType == constants.ETF {
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_etf_macd_gold_cross t "+
						"where t.etf_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
				}
				if sellOrBuyPrice > 0 {
					doSellBuy = true
				}
			}
			// 收盘价死叉五日均线
			if robot7StockTransactRecord.FilterType == constants.CLOSE_PRICE_MA5_GOLD_CROSS {
				// 股票
				if properties.Robot7Properties_.TransactionStrategyInBull == 2 && robot7StockTransactRecord.TransactionType == constants.STOCK {
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_close_price_ma5_g_c t "+
						"where t.etf_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
				}
				// ETF
				if properties.Robot7Properties_.TransactionStrategyInShort == 2 && robot7StockTransactRecord.TransactionType == constants.ETF {
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_etf_close_price_ma5_g_c t "+
						"where t.etf_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
				}
				if sellOrBuyPrice > 0 {
					doSellBuy = true
				}
			}
			// 平均K线是否从上涨趋势变为下跌趋势
			if robot7StockTransactRecord.FilterType == constants.HEI_KIN_ASHI_UP {
				// 股票
				if properties.Robot7Properties_.TransactionStrategyInBull == 2 && robot7StockTransactRecord.TransactionType == constants.STOCK {
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_hei_kin_ashi_down_up t "+
						"where t.etf_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
				}
				// ETF
				if properties.Robot7Properties_.TransactionStrategyInShort == 2 && robot7StockTransactRecord.TransactionType == constants.ETF {
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_etf_hei_kin_ashi_down_up t "+
						"where t.etf_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
				}
				if sellOrBuyPrice > 0 {
					doSellBuy = true
				}
			}
			// KD死叉
			if robot7StockTransactRecord.FilterType == constants.KD_GOLD_CROSS {
				// 股票
				if properties.Robot7Properties_.TransactionStrategyInBull == 2 && robot7StockTransactRecord.TransactionType == constants.STOCK {
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_kd_gold_cross t "+
						"where t.etf_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
				}
				// ETF
				if properties.Robot7Properties_.TransactionStrategyInShort == 2 && robot7StockTransactRecord.TransactionType == constants.ETF {
					_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_etf_kd_gold_cross t "+
						"where t.etf_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
						robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
				}
				if sellOrBuyPrice > 0 {
					doSellBuy = true
				}
			}

			// 无论第二天是涨是跌，全部卖出
			if (robot7StockTransactRecord.TransactionType == constants.STOCK && properties.Robot7Properties_.TransactionStrategyInBull == 3) ||
				(robot7StockTransactRecord.TransactionType == constants.ETF && properties.Robot7Properties_.TransactionStrategyInShort == 3) {
				io.Infoln("股票[%s]，无论第二天是涨是跌，全部卖出", robot7StockTransactRecord.StockCode)
				doSellBuy = true
			}

			// 判断是否是死叉，如果不是死叉，则返回下一条记录
			if (robot7StockTransactRecord.TransactionType == constants.STOCK && properties.Robot7Properties_.TransactionStrategyInBull == 4) ||
				(robot7StockTransactRecord.TransactionType == constants.ETF && properties.Robot7Properties_.TransactionStrategyInShort == 4) {
				var sellOrBuyPrice float64 = 0
				// MACD死叉
				if robot7StockTransactRecord.FilterType == constants.CLOSE_PRICE_GOLD_CROSS_BULL_SHORT_LINE {
					// 股票
					if robot7StockTransactRecord.TransactionType == constants.STOCK {
						_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_bull_short_line_up t "+
							"where t.stock_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
							robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
					}
					// ETF
					if robot7StockTransactRecord.TransactionType == constants.ETF {
						_robot7StockTransactRecordDaoImpl.db.Raw("select t.sell_price from mdl_etf_bull_short_line_up t "+
							"where t.etf_code = ? and t.sell_date = to_date(?, 'yyyy-mm-dd')",
							robot7StockTransactRecord.StockCode, currentDate).Scan(&sellOrBuyPrice)
					}
					if sellOrBuyPrice > 0 {
						doSellBuy = true
					}
				}
			}

			if doSellBuy == true {
				// 如果是死叉，则卖出这支ETF
				// 更新robot7_stock_transact_record表的sell_date、sell_price和sell_amount字段
				_robot7StockTransactRecordDaoImpl.db.Exec("update robot7_stock_transact_record t "+
					"set t.sell_date = to_date(?, 'yyyy-mm-dd'), t.sell_price  = ?, t.sell_amount = t.buy_amount,"+
					"t.stamp_duty = ROUND(t.buy_amount * "+fmt.Sprintf("%f", closePrice)+" * "+fmt.Sprintf("%f", properties.Robot7Properties_.StampDutyRate)+", 2),"+
					"t.registration_fee_when_sell = ?,"+
					"t.commission_when_sell = ? "+
					"where t.id_ = ?",
					currentDate, closePrice,
					util.CalculateRegistrationFee(robot7StockTransactRecord.StockCode, robot7StockTransactRecord.BuyAmount),
					util.CalculateCommission(closePrice, robot7StockTransactRecord.BuyAmount),
					robot7StockTransactRecord.ID)

				// 更新robot7_stock_transact_record表的profit_and_loss和profit_and_loss_rate字段
				_robot7StockTransactRecordDaoImpl.db.Exec("update robot7_stock_transact_record t "+
					"set t.profit_and_loss = ROUND((t.sell_price * t.sell_amount) - (t.buy_price * t.buy_amount)), "+
					"t.profit_and_loss_rate = (t.sell_price - t.buy_price) / t.buy_price * 100 "+
					"where t.id_ = ?", robot7StockTransactRecord.ID)
			}
		}
	}
}

// 买股票。用于做多
func (_robot7StockTransactRecordDaoImpl *Robot7StockTransactRecordDaoImpl) BuyOrSell_stock(date string, transactionStrategy int, maxHoldStockNumberInBull int) {
	io.Infoln("买股票。用于做多")

	// 获取所有账户信息
	var robot7AccountArray model.Robot7AccountArray
	_robot7StockTransactRecordDaoImpl.db.Table("robot7_account").Select("*").Order("id_ asc").Find(&robot7AccountArray)
	for _, robot7Account := range robot7AccountArray {
		// 如果当前账户的持股数量已经大于等于最大持股数量，则查找下一个机器人账户
		if robot7Account.HoldStockNumber >= maxHoldStockNumberInBull {
			io.Infoln("账户[%s]持股数量已经是[%d]，不再买入股票", robot7Account.RobotName, robot7Account.HoldStockNumber)
			continue
		}

		var robot7StockFilterArray model.Robot7StockFilterArray
		if properties.Robot7Properties_.StockSortStrategyInBull == 1 {
			// 按照accumulative_profit_loss列降序排列，取前MaxHoldStockNumberInBull条记录；如果robot7_stock_filter表中已经没有数据了，则查找下一个机器人
			_robot7StockTransactRecordDaoImpl.db.Raw("select * from ("+
				"select * from robot7_stock_filter t order by t.accumulative_profit_loss desc) "+
				"where rownum <= ?", maxHoldStockNumberInBull-robot7Account.HoldStockNumber).Scan(&robot7StockFilterArray)
		}
		if properties.Robot7Properties_.StockSortStrategyInBull == 2 {
			// 按照variance列降序排列，取前MaxHoldStockNumberInBull条记录；如果robot7_stock_filter表中已经没有数据了，则查找下一个机器人
			_robot7StockTransactRecordDaoImpl.db.Raw("select * from ("+
				"select * from robot7_stock_filter t order by t.variance desc) "+
				"where rownum <= ?", maxHoldStockNumberInBull-robot7Account.HoldStockNumber).Scan(&robot7StockFilterArray)
		}
		if properties.Robot7Properties_.StockSortStrategyInBull == 4 {
			// 按照last_five_day_yield_rate降序排列；如果robot7_stock_filter表中已经没有数据了，则查找下一个机器人
			_robot7StockTransactRecordDaoImpl.db.Raw("select * from ("+
				"select * from robot7_stock_filter t order by t.last_five_day_yield_rate asc) "+
				"where rownum <= ?", maxHoldStockNumberInBull-robot7Account.HoldStockNumber).Scan(&robot7StockFilterArray)
		}

		if len(robot7StockFilterArray) == 0 {
			// 说明这一天没有可以进行交易的股票
			io.Infoln("表[robot7_stock_filter]为空")
			break
		} else {
			for _, robot7StockFilter := range robot7StockFilterArray {
				// 查找这只股票的收盘价
				var closePrice float64
				_robot7StockTransactRecordDaoImpl.db.Raw("select t.close_price from stock_transaction_data_all t "+
					"where t.code_ = ? and t.date_ = to_date(?, 'yyyy-mm-dd')",
					robot7StockFilter.StockCode, date).Scan(&closePrice)

				// 如果股票的收盘价过高，或者资金资产太少，连一手也买不了，则直接查找下一个机器人
				if util.CalculateBuyStockFee(robot7StockFilter.StockCode, closePrice, 100) > float64(robot7Account.CapitalAssets) {
					break
				}

				// 如果可以买，则向robot7_stock_transact_record表中插入数据，从robot7_stock_filter表中删除这条记录。
				// 计算应该买入股票的数量
				// robot7_stock_filter表的记录数
				var robot7StockFilterNumber int = -1
				_robot7StockTransactRecordDaoImpl.db.Raw("select count(*) from robot7_stock_filter").Scan(&robot7StockFilterNumber)

				// 应当买入的股票的数量
				var shouldBuyStockNumber int = -1
				if robot7StockFilterNumber <=
					(maxHoldStockNumberInBull - robot7Account.HoldStockNumber) {
					shouldBuyStockNumber = robot7StockFilterNumber
				} else {
					shouldBuyStockNumber = maxHoldStockNumberInBull - robot7Account.HoldStockNumber
				}

				// 判断是否需要继续买入
				if shouldBuyStockNumber == 0 {
					io.Infoln("账号[%s]持股数量已经是%d，不再需要买入股票", robot7Account.RobotName, maxHoldStockNumberInBull)
					break
				}

				// 计算买多少股
				// 买入多少股
				var buyOrSellAmount int = 100

				for robot7Account.CapitalAssets/float64(maxHoldStockNumberInBull-robot7Account.HoldStockNumber) >= util.CalculateBuyStockFee(robot7StockFilter.StockCode, closePrice, buyOrSellAmount) {
					if util.CalculateBuyStockFee(robot7StockFilter.StockCode, closePrice, buyOrSellAmount) >= robot7Account.CapitalAssets/float64(maxHoldStockNumberInBull-robot7Account.HoldStockNumber) {
						break
					}
					buyOrSellAmount = buyOrSellAmount + 100
				}
				if robot7Account.CapitalAssets/float64(maxHoldStockNumberInBull-robot7Account.HoldStockNumber) < util.CalculateBuyStockFee(robot7StockFilter.StockCode, closePrice, buyOrSellAmount) {
					if buyOrSellAmount == 100 {
						// 从robot7_stock_filter表中删除这条记录
						_robot7StockTransactRecordDaoImpl.db.Exec("delete from robot7_stock_filter t where t.stock_code = ?",
							robot7StockFilter.StockCode)

						continue
					} else {
						buyOrSellAmount = buyOrSellAmount - 100
					}
				}

				// 向robot7_stock_transact_record表中插入数据
				// 做多
				if robot7StockFilter.Direction == constants.BULL {
					_robot7StockTransactRecordDaoImpl.db.Exec("insert into robot7_stock_transact_record("+
						"robot_name, stock_code, buy_date, buy_price, buy_amount, filter_type, direction, "+
						"transaction_type, registration_fee_when_buy, commission_when_buy) "+
						"values(?, ?, to_date(?, 'yyyy-mm-dd'), ?, ?, ?, ?, ?, ?, ?)",
						robot7Account.RobotName, robot7StockFilter.StockCode, date,
						closePrice, buyOrSellAmount, robot7StockFilter.FilterType, robot7StockFilter.Direction,
						1, util.CalculateRegistrationFee(robot7StockFilter.StockCode, buyOrSellAmount),
						util.CalculateCommission(closePrice, buyOrSellAmount))
				}

				// 计算这支股票的持股数量、资金资产
				robot7Account.HoldStockNumber = robot7Account.HoldStockNumber + 1
				robot7Account.CapitalAssets = float64(robot7Account.CapitalAssets) - (util.CalculateBuyStockFee(robot7StockFilter.StockCode, closePrice, buyOrSellAmount))

				// 从robot7_stock_filter表中删除这条记录
				_robot7StockTransactRecordDaoImpl.db.Exec("delete from robot7_stock_filter t where t.stock_code = ?",
					robot7StockFilter.StockCode)
			}
		}
	}
}

// ETF加仓
func (_robot7StockTransactRecordDaoImpl *Robot7StockTransactRecordDaoImpl) AddPosition(date string, maxHoldStockNumberInShort int) {
	if properties.Robot7Properties_.EnableAddPosition == true {
		io.Infoln("ETF加仓")

		// 获取所有账户信息
		var robot7AccountArray model.Robot7AccountArray
		_robot7StockTransactRecordDaoImpl.db.Table("robot7_account").Select("*").Order("id_ asc").Find(&robot7AccountArray)
		for _, robot7Account := range robot7AccountArray {
			// 保存ETF的code列表
			var etfCodeArray []string

			// 已经加过仓的ETF
			_robot7StockTransactRecordDaoImpl.db.Raw("select distinct t.stock_code from robot7_stock_transact_record t "+
				"where t.robot_name=? and t.sell_date is null group by t.stock_code having count(*)>1",
				robot7Account.RobotName).Scan(&etfCodeArray)
			for _, etfCode := range etfCodeArray {
				// 如果当前账户的持ETF数量已经大于等于最大持ETF数量，则查找下一个机器人账户
				if robot7Account.HoldStockNumber >= maxHoldStockNumberInShort {
					io.Infoln("账户[%s]持ETF数量已经是[%d]，不再买入ETF", robot7Account.RobotName, robot7Account.HoldStockNumber)
					break
				}

				// 判断单一ETF品种的持仓量是否到达设置
				var certainEtfHoldingNumber int
				_robot7StockTransactRecordDaoImpl.db.Raw("select count(*) from robot7_stock_transact_record t "+
					"where t.robot_name=? and t.stock_code=? and t.sell_date is null",
					robot7Account.RobotName, etfCode).Scan(&certainEtfHoldingNumber)
				if certainEtfHoldingNumber >= properties.Robot7Properties_.MaxAddPositionNumber {
					io.Infoln("账户[%s]持ETF[%d]数量已经是[%d]，不再买入该ETF", robot7Account.RobotName, etfCode, certainEtfHoldingNumber)
					continue
				}

				// 最近一次加仓的记录
				var robot7StockTransactRecord model.Robot7StockTransactRecord
				_robot7StockTransactRecordDaoImpl.db.Raw("select * from (select * from robot7_stock_transact_record t "+
					"where t.robot_name=? and t.sell_date is null and t.stock_code=? order by t.buy_date desc) "+
					"where rownum<=1",
					robot7Account.RobotName, etfCode).Scan(&robot7StockTransactRecord)
				// 当前这个etf的交易记录
				var etfTransactionData model.EtfTransactionData
				_robot7StockTransactRecordDaoImpl.db.Raw("select * from etf_transaction_data t where t.date_=to_date(?, 'yyyy-mm-dd') "+
					"and t.code_=?", date, etfCode).Scan(&etfTransactionData)
				// 如果最近一次加仓后，涨幅到达/超过了阈值，则加仓
				if (etfTransactionData.ClosePrice-robot7StockTransactRecord.BuyPrice)/robot7StockTransactRecord.BuyPrice >= properties.Robot7Properties_.AddOnePositionPerProfitRate {
					// 如果ETF的收盘价过高，或者资金资产太少，连一手也买不了，则直接查找下一个机器人
					if util.CalculateBuyStockFee(etfTransactionData.Code, etfTransactionData.ClosePrice, 100) > float64(robot7Account.CapitalAssets) {
						break
					}

					// 计算买多少ETF
					// 买入多少ETF
					var buyOrSellAmount int = 100

					for robot7Account.CapitalAssets/float64(maxHoldStockNumberInShort-robot7Account.HoldStockNumber) >= util.CalculateBuyStockFee(etfTransactionData.Code, etfTransactionData.ClosePrice, buyOrSellAmount) {
						if util.CalculateBuyStockFee(etfTransactionData.Code, etfTransactionData.ClosePrice, buyOrSellAmount) >= robot7Account.CapitalAssets/float64(maxHoldStockNumberInShort-robot7Account.HoldStockNumber) {
							break
						}
						buyOrSellAmount = buyOrSellAmount + 100
					}
					if robot7Account.CapitalAssets/float64(maxHoldStockNumberInShort-robot7Account.HoldStockNumber) < util.CalculateBuyStockFee(etfTransactionData.Code, etfTransactionData.ClosePrice, buyOrSellAmount) {
						if buyOrSellAmount == 100 {
							continue
						} else {
							buyOrSellAmount = buyOrSellAmount - 100
						}
					}

					// 向robot7_stock_transact_record表中插入数据
					_robot7StockTransactRecordDaoImpl.db.Exec("insert into robot7_stock_transact_record("+
						"robot_name, stock_code, buy_date, buy_price, buy_amount, filter_type, direction, "+
						"transaction_type, registration_fee_when_buy, commission_when_buy) "+
						"values(?, ?, to_date(?, 'yyyy-mm-dd'), ?, ?, ?, ?, ?, ?, ?)",
						robot7Account.RobotName, etfTransactionData.Code, date,
						etfTransactionData.ClosePrice, buyOrSellAmount, constants.CLOSE_PRICE_GOLD_CROSS_BULL_SHORT_LINE, constants.BULL,
						2, util.CalculateRegistrationFee(etfTransactionData.Code, buyOrSellAmount),
						util.CalculateCommission(etfTransactionData.ClosePrice, buyOrSellAmount))

					// 计算这支ETF的持股数量、资金资产
					robot7Account.HoldStockNumber = robot7Account.HoldStockNumber + 1
					robot7Account.CapitalAssets = float64(robot7Account.CapitalAssets) - (util.CalculateBuyStockFee(etfTransactionData.Code, etfTransactionData.ClosePrice, buyOrSellAmount))
				}
			}

			// 没有加过仓的ETF
			_robot7StockTransactRecordDaoImpl.db.Raw("select distinct t.stock_code from robot7_stock_transact_record t "+
				"where t.robot_name=? and t.sell_date is null group by t.stock_code having count(*)=1",
				robot7Account.RobotName).Scan(&etfCodeArray)
			for _, etfCode := range etfCodeArray {
				// 如果当前账户的持ETF数量已经大于等于最大持ETF数量，则查找下一个机器人账户
				if robot7Account.HoldStockNumber >= maxHoldStockNumberInShort {
					io.Infoln("账户[%s]持ETF数量已经是[%d]，不再买入ETF", robot7Account.RobotName, robot7Account.HoldStockNumber)
					break
				}

				// 这个ETF的持仓记录
				var robot7StockTransactRecord model.Robot7StockTransactRecord
				_robot7StockTransactRecordDaoImpl.db.Raw("select * from robot7_stock_transact_record t "+
					"where t.robot_name=? and t.sell_date is null and t.stock_code=? order by t.buy_date desc",
					robot7Account.RobotName, etfCode).Scan(&robot7StockTransactRecord)
				// 当前这个etf的交易记录
				var etfTransactionData model.EtfTransactionData
				_robot7StockTransactRecordDaoImpl.db.Raw("select * from etf_transaction_data t where t.date_=to_date(?, 'yyyy-mm-dd') "+
					"and t.code_=?", date, etfCode).Scan(&etfTransactionData)
				// 如果这个etf持仓后，涨幅到达/超过了阈值，则加仓
				if (etfTransactionData.ClosePrice-robot7StockTransactRecord.BuyPrice)/robot7StockTransactRecord.BuyPrice >= properties.Robot7Properties_.AddOnePositionPerProfitRate {
					// 如果ETF的收盘价过高，或者资金资产太少，连一手也买不了，则直接查找下一个机器人
					if util.CalculateBuyStockFee(etfTransactionData.Code, etfTransactionData.ClosePrice, 100) > float64(robot7Account.CapitalAssets) {
						break
					}

					// 计算买多少ETF
					// 买入多少ETF
					var buyOrSellAmount int = 100

					for robot7Account.CapitalAssets/float64(maxHoldStockNumberInShort-robot7Account.HoldStockNumber) >= util.CalculateBuyStockFee(etfTransactionData.Code, etfTransactionData.ClosePrice, buyOrSellAmount) {
						if util.CalculateBuyStockFee(etfTransactionData.Code, etfTransactionData.ClosePrice, buyOrSellAmount) >= robot7Account.CapitalAssets/float64(maxHoldStockNumberInShort-robot7Account.HoldStockNumber) {
							break
						}
						buyOrSellAmount = buyOrSellAmount + 100
					}
					if robot7Account.CapitalAssets/float64(maxHoldStockNumberInShort-robot7Account.HoldStockNumber) < util.CalculateBuyStockFee(etfTransactionData.Code, etfTransactionData.ClosePrice, buyOrSellAmount) {
						if buyOrSellAmount == 100 {
							continue
						} else {
							buyOrSellAmount = buyOrSellAmount - 100
						}
					}

					// 向robot7_stock_transact_record表中插入数据
					_robot7StockTransactRecordDaoImpl.db.Exec("insert into robot7_stock_transact_record("+
						"robot_name, stock_code, buy_date, buy_price, buy_amount, filter_type, direction, "+
						"transaction_type, registration_fee_when_buy, commission_when_buy) "+
						"values(?, ?, to_date(?, 'yyyy-mm-dd'), ?, ?, ?, ?, ?, ?, ?)",
						robot7Account.RobotName, etfTransactionData.Code, date,
						etfTransactionData.ClosePrice, buyOrSellAmount, constants.CLOSE_PRICE_GOLD_CROSS_BULL_SHORT_LINE, constants.BULL,
						2, util.CalculateRegistrationFee(etfTransactionData.Code, buyOrSellAmount),
						util.CalculateCommission(etfTransactionData.ClosePrice, buyOrSellAmount))

					// 计算这支ETF的持股数量、资金资产
					robot7Account.HoldStockNumber = robot7Account.HoldStockNumber + 1
					robot7Account.CapitalAssets = float64(robot7Account.CapitalAssets) - (util.CalculateBuyStockFee(etfTransactionData.Code, etfTransactionData.ClosePrice, buyOrSellAmount))
				}
			}
		}
	}
}

// 买ETF。用于做多
func (_robot7StockTransactRecordDaoImpl *Robot7StockTransactRecordDaoImpl) BuyOrSell_etf(date string, transactionStrategy int, maxHoldStockNumberInShort int) {
	io.Infoln("买ETF。用于做多")

	// 获取所有账户信息
	var robot7AccountArray model.Robot7AccountArray
	_robot7StockTransactRecordDaoImpl.db.Table("robot7_account").Select("*").Order("id_ asc").Find(&robot7AccountArray)
	for _, robot7Account := range robot7AccountArray {
		// 如果当前账户的持ETF数量已经大于等于最大持ETF数量，则查找下一个机器人账户
		if robot7Account.HoldStockNumber >= maxHoldStockNumberInShort {
			io.Infoln("账户[%s]持ETF数量已经是[%d]，不再买入ETF", robot7Account.RobotName, robot7Account.HoldStockNumber)
			continue
		}

		var robot7StockFilterArray model.Robot7StockFilterArray
		if properties.Robot7Properties_.StockSortStrategyInShort == 3 {
			// 按照correlation250_with_avg_c_p升降序排列；如果robot7_stock_filter表中已经没有数据了，则查找下一个机器人
			_robot7StockTransactRecordDaoImpl.db.Raw("select t.* from robot7_stock_filter t "+
				"join etf_transaction_data etd on etd.code_=t.stock_code "+
				"where etd.date_=to_date(?,'yyyy-mm-dd') "+
				"order by etd.correlation250_with_avg_c_p asc", date).Scan(&robot7StockFilterArray)
		}

		if len(robot7StockFilterArray) == 0 {
			// 说明这一天没有可以进行交易的ETF
			io.Infoln("表robot7_stock_filter为空")
			break
		} else {
			for _, robot7StockFilter := range robot7StockFilterArray {
				// 查找这只ETF的收盘价
				var closePrice float64
				_robot7StockTransactRecordDaoImpl.db.Raw("select t.close_price from etf_transaction_data t "+
					"where t.code_ = ? and t.date_ = to_date(?, 'yyyy-mm-dd')",
					robot7StockFilter.StockCode, date).Scan(&closePrice)

				// 如果ETF的收盘价过高，或者资金资产太少，连一手也买不了，则直接查找下一个机器人
				if util.CalculateBuyStockFee(robot7StockFilter.StockCode, closePrice, 100) > float64(robot7Account.CapitalAssets) {
					break
				}

				// 如果可以买，则向robot7_stock_transact_record表中插入数据，从robot7_stock_filter表中删除这条记录。
				// 计算应该买入ETF的数量
				// robot7_stock_filter表的记录数
				var robot7StockFilterNumber int = -1
				_robot7StockTransactRecordDaoImpl.db.Raw("select count(*) from robot7_stock_filter").Scan(&robot7StockFilterNumber)

				// 应当买入的ETF的数量
				var shouldBuyStockNumber int = -1
				if robot7StockFilterNumber <=
					(maxHoldStockNumberInShort - robot7Account.HoldStockNumber) {
					shouldBuyStockNumber = robot7StockFilterNumber
				} else {
					shouldBuyStockNumber = maxHoldStockNumberInShort - robot7Account.HoldStockNumber
				}

				// 判断是否需要继续买入
				if shouldBuyStockNumber == 0 {
					io.Infoln("账号[%s]持ETF数量已经是%d，不再需要买入ETF", robot7Account.RobotName, maxHoldStockNumberInShort)
					break
				}

				// 计算买多少ETF
				// 买入多少ETF
				var buyOrSellAmount int = 100

				for robot7Account.CapitalAssets/float64(maxHoldStockNumberInShort-robot7Account.HoldStockNumber) >= util.CalculateBuyStockFee(robot7StockFilter.StockCode, closePrice, buyOrSellAmount) {
					if util.CalculateBuyStockFee(robot7StockFilter.StockCode, closePrice, buyOrSellAmount) >= robot7Account.CapitalAssets/float64(maxHoldStockNumberInShort-robot7Account.HoldStockNumber) {
						break
					}
					buyOrSellAmount = buyOrSellAmount + 100
				}
				if robot7Account.CapitalAssets/float64(maxHoldStockNumberInShort-robot7Account.HoldStockNumber) < util.CalculateBuyStockFee(robot7StockFilter.StockCode, closePrice, buyOrSellAmount) {
					if buyOrSellAmount == 100 {
						// 从robot7_stock_filter表中删除这条记录
						_robot7StockTransactRecordDaoImpl.db.Exec("delete from robot7_stock_filter t where t.stock_code = ?",
							robot7StockFilter.StockCode)

						continue
					} else {
						buyOrSellAmount = buyOrSellAmount - 100
					}
				}

				// 向robot7_stock_transact_record表中插入数据
				// 做多
				if robot7StockFilter.Direction == constants.BULL {
					_robot7StockTransactRecordDaoImpl.db.Exec("insert into robot7_stock_transact_record("+
						"robot_name, stock_code, buy_date, buy_price, buy_amount, filter_type, direction, "+
						"transaction_type, registration_fee_when_buy, commission_when_buy) "+
						"values(?, ?, to_date(?, 'yyyy-mm-dd'), ?, ?, ?, ?, ?, ?, ?)",
						robot7Account.RobotName, robot7StockFilter.StockCode, date,
						closePrice, buyOrSellAmount, robot7StockFilter.FilterType, robot7StockFilter.Direction,
						2, util.CalculateRegistrationFee(robot7StockFilter.StockCode, buyOrSellAmount),
						util.CalculateCommission(closePrice, buyOrSellAmount))
				}

				// 计算这支ETF的持股数量、资金资产
				robot7Account.HoldStockNumber = robot7Account.HoldStockNumber + 1
				robot7Account.CapitalAssets = float64(robot7Account.CapitalAssets) - (util.CalculateBuyStockFee(robot7StockFilter.StockCode, closePrice, buyOrSellAmount))

				// 从robot7_stock_filter表中删除这条记录
				_robot7StockTransactRecordDaoImpl.db.Exec("delete from robot7_stock_filter t where t.stock_code = ?",
					robot7StockFilter.StockCode)
			}
		}
	}
}
